package com.zb.zeus.auth.config;

import com.baomidou.dynamic.datasource.creator.DruidDataSourceCreator;
import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DataSourceProperty;
import lombok.AllArgsConstructor;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.SmartInitializingSingleton;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.config.annotation.builders.JdbcClientDetailsServiceBuilder;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.code.AuthorizationCodeServices;
import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices;
import org.springframework.security.oauth2.provider.token.DefaultTokenServices;
import org.springframework.security.oauth2.provider.token.TokenEnhancerChain;
import org.springframework.security.oauth2.provider.token.TokenStore;

import javax.sql.DataSource;


/**
 * @author fujianjian
 * @date 2023/3/23 15:43
 **/
@Configuration
@AllArgsConstructor
@EnableAuthorizationServer
public class ZeusAuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter {

    private final TokenStore tokenStore;

    private final PasswordEncoder passwordEncoder;

    // private final ClientDetailsService clientDetailsService;
    private final DataSource oauthDataSource;

    private final AuthenticationManager authenticationManager;

    private final AuthorizationCodeServices authorizationCodeServices;


    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {

        JdbcClientDetailsServiceBuilder builder = clients.jdbc(oauthDataSource);
        builder.passwordEncoder(passwordEncoder);
        // clients.inMemory()
        //         .withClient("client_1")
        //         .secret(passwordEncoder.encode("123456"))
        //         .authorizedGrantTypes("authorization_code", "password", "client_credentials", "implicit", "refresh_token")
        //         .scopes("all")
        //         .autoApprove(false);
    }

    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        endpoints.authenticationManager(authenticationManager)
                .authorizationCodeServices(authorizationCodeServices)
                .tokenServices(authorizationServerTokenServices())
                .allowedTokenEndpointRequestMethods(HttpMethod.GET, HttpMethod.POST);
    }

    @Override
    public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
        security
                // oauth/check_token 公开访问
                .checkTokenAccess("permitAll()")
                // oauth/token_key 公开访问
                .tokenKeyAccess("permitAll()")
                // 允许表单认证
                .allowFormAuthenticationForClients();
    }

    public AuthorizationServerTokenServices authorizationServerTokenServices() {
        DefaultTokenServices tokenServices = new DefaultTokenServices();
        tokenServices.setTokenStore(tokenStore);
        tokenServices.setSupportRefreshToken(true);

        //令牌强
        TokenEnhancerChain tokenEnhancerChain = new TokenEnhancerChain();

        tokenServices.setTokenEnhancer(tokenEnhancerChain);
        tokenServices.setAccessTokenValiditySeconds(7200);
        tokenServices.setRefreshTokenValiditySeconds(259200);
        return tokenServices;
    }

    @Configuration
    @RequiredArgsConstructor
    public static class OauthDataSourceConfiguration implements SmartInitializingSingleton {

        private final DruidDataSourceCreator dataSourceCreator;

        @Bean
        @ConfigurationProperties("zeus.oauth")
        DataSourceProperty zeusOauthDataSourceProperty() {
            return new DataSourceProperty();
        }

        @Bean
        public DataSource oauthDataSource(DataSourceProperty zeusOauthDataSourceProperty) {
            return dataSourceCreator.createDataSource(zeusOauthDataSourceProperty);
        }



        @Override
        public void afterSingletonsInstantiated() {

        }
    }
}
